/*
 * 事件
 */
//事件冒泡、事件捕获
//DOM事件流：事件捕获阶段、处于目标阶段、事件冒泡阶段
//事件处理程序：addEventListener() , removeEventListenter()
btn.addEventListener("click", function() {

}, false); //false 为冒泡阶段触发，true 为捕获阶段调用事件处理程序
//IE事件处理程序：attachEvent(),datachEvent()
btn.attachEvent("onclick", function() {
	alert("IE Event");
})

//跨浏览器的事件处理程序
var EventUtil = {
	addHandler: function(element, type, handler) {
		if (element.addEventListener) {
			element.addEventListener(type, handler, false);
		} else if (element.attachEvent) {
			element.attachEvent("on" + type, handler);
		} else {
			element["on" + type] = handler;
		}
	},
	removeHandler: function(element, type, handler) {
		if (element.removeEventListenter) {
			element.removeEventListenter(type, handler, false);
		} else if (element.detachEvent) {
			element.detachEvent("on" + type, handler);
		} else {
			element["on" + type] = null
		}
	}，
	getEvent: function(event) {
		return event ? event : window.event;
	},
	getTarget: function(event) {
		return event.target || event.srcElement;
	},
	preventDefault: function(event) {
		if (event.preventDefault) {
			event.preventDefault();
		} else {
			event.returnValue = false;
		}
	},
	stopPropagation: function(event) {
		if (event.stopPropagation) {
			event.stopPropagation();
		} else {
			event.cancelBubble = true;
		}
	},
	getRelatedTarget: function(event) {
		if (event.relatedTarget) {
			return event.relatedTarget;
		} else if (event.toElement) {
			return event.toElement;
		} else if (event.fromElement) {
			return event.fromElement;
		} else {
			return null;
		}
	},
	getButton: function(event) {
		if (document.implementation.hasFeature("mouseEvent", "2.0")) {
			return event.button;
		} else {
			switch (event.button) {
				case 0:
				case 1:
				case 3:
				case 5:
				case 7:
					return 0;
				case 2:
				case 6:
					return 2;
				case 4:
					return 1;
			}
		}
	},
	getWheelDelta: function(event) {
		if (event.wheelDelta) {
			return (client.engine.opera && client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta);
		} else {
			return -event.detail * 40;
		}
	}，
	getCharCode: function(event) {
		if (typeof event.charCode == "number") {
			return event.charCode;
		} else {
			return event.keyCode;
		}
	}
}

//UI事件
//DOMActivate 兼容性不够，不建议使用
//load 、unload 、abort 、error 、select 、resize 、scroll
//
//焦点事件
//blur 、DOMFocusIn(focusin) 、DOMFocusOut(focusout) 、focus
//
//鼠标与滚动事件
//click 、dblclick 、mousedown 、mouseenter 、mouseleave 、mousemove 、mouseout 、mouseover 、mouseup
//修改键：shiftKey 、ctrlKey 、altKey 、metaKey
//更多的事件信息：altLeft 、ctrlLeft 、offsetX 、offsetY 、shiftLeft
//鼠标滚动事件：mousewheel
//inputMethod
//
//键盘与文本事件
//键盘事件：keydown 、keypress 、keyup。文本事件：textInput
//键码：keyCode
//字符编码：charCode
//DOM3不再包含 charCode 属性，而是保护两个新属性：key 和 char
//
//复合事件
//compositionstart 、compositionupdate 、compositionend
//
//变得事件：DOMSubtreeModified 、DOMNodeRemoved 、DOMNodeInserted 、DOMNodeInsertedDocument 、
//DOMNodeRemovedFromDocument 、DOMAttrModified 、DOMCharacterDataModified
// 删除节点：removeChild() 、replaceChild()
// 插入节点：appendChild() 、replaceChild() 、insertBefore()
//
//HTML5事件
//contextmenu 事件
//beforeunload 事件
//DOMContentLoaded 事件
//readystatechange 事件：unintialized , loading , loaded , interactive , complete
//pageshow 和 pagehide 事件
//haschang 事件：oldURL 和 newURL 属性
//
//设备事件 ( orientation : 方向 )
//orientationchange 事件 window.orientation 设备的方向
//MozOrientation 事件：event 对象包含三个属性：x 、y 、z 设备的方向
//deviceorientation 事件：设备是否移动，x 、y 、z 轴来定位，事件包含五个属性：
// alpha：在围绕 z 轴旋转时（即左右旋转时），y 轴的度数差，是一个介于 0 到 360 之间的浮点数
// beta：在围绕 x 轴旋转时（即前后旋转时），z 轴的度数差，是一个介于 -180 到 180 是之间的浮点数
// gamma：在围绕 y 轴旋转时（即扭转设备时），z 轴的度数差，是一个介于 -90 到 90 之间的的浮点数
// absolute：布尔值，表示设备是否返回一个绝对值
// compassCalibrated：布尔值，表示设备的指南针是否校准过
//
//devicemotion 事件：设备什么时候移动，不仅仅是设备方向如何改变
//触发 devicemotion 事件时，事件对象包含以下属性：
// acceleration ：一个包含 x 、y 、z 属性的对象，在不考虑重力的情况下，告诉你在每个方向上的速度
// accelerationIncludingGravity：一个包含 x 、y 和 z 属性的对象，在考虑 z 轴自然重力加速的情况下，告诉你在每个方向上的加速度
// interval：以毫秒表示时间值，必须在另一个 devicemotion 事件触发前传入。这个值在每个事件中应该是一个常量
// rotationRate：一个包含 alpha 、beta 、gamma 属性的对象。
//
//
//触摸与手势
//触摸事件：（ touchstart 、touchmove 、touchend 、touchcancel ）冒泡 、（ touches 、targetTouchs 、changeTouches ）跟踪触摸的属性
//每个 Touch 对象包含下列属性：
// clientX：触摸目标在视口中的 x 坐标
// clientY：触摸末班在视口中的 y 坐标
// identifier：标识触摸的唯一ID
// pageX：触摸目标在页面中的 x 坐标
// pageY：触摸目标在页面中的 y 坐标
// screenX：触摸目标在屏幕中的 x 坐标
// screenY：触摸目标在屏幕中的 y 坐标
// target：触摸的 DOM 节点目标
//
//手势事件
// gesturestart：当一个手指已经按在屏幕上而另一个手指有触摸屏幕时触发
// gesturechange：当触摸屏幕的任何一个手指的位置的位置发生变化时触发
// gestureend：当任何一个手指从屏幕上面移开时触发
//
//
//
//内存和性能
//事件委托
var list = document.getElementById("mylink");
EventUtil.addHandler(list, "click", function(event) {
		event = EventUtil.getEvent(event);
		var target = EventUtil.getTarget(event);

		switch (target.id) {
			case "doSomething":
				document.title = "我改变了文档标题"；
				break;
			case "goSomewhere":
				location.href = "http://www.baidu.com";
				break;
			case "sayHi":
				console.log("hello word!");
				break;
		}
	})
	//移除事件处理程序：btn.onclick=null
	//
	//模拟事件
	//DOM 中的模拟事件：UIEvents 、MouseEvents 、MutationEvents 、HTMLEvent
var btn = document.getElementById("myBtn");
var event = document.createEvent("MouseEvents"); //创建事件对象
event.initMouseEvent("click", true, true, document.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0, null); //初始化事件对象
btn.dispatchEvent(event); //触发
//
//模拟键盘事件
var textbox = document.getElementById("myTextbox"),
	event;
//以 DOM3 级方式创建事件对象
if (document.implementtaion.hasFeature("KeyboardEvents", "3.0")) {
	event = document.createEvent("KeyboardEvent");

	//初始化事件对象
	event.initKeyboardEvent("keydown", true, true, document.defaultView, "a", 0, "Shift", 0);
}
textbox.dispatchEvent(event); //触发事件
//
//模拟其他事件：createEvent("MutationEvents") 、initMutationEvent()
//
//自定义DOM事件：createEvent("CustomEvent") 、initCustomEvent()
//
//IE中的事件模拟：document.createEventObject() 创建对象，fireEvent() 触发事件
//


// 事件
// 一、EventTarget 接口
// 1、概述：DOM 的事件操作（监听和触发），都定义在EventTarget接口。所有节点对象都部署了这个接口，其他一些需要事件通信的浏览器内置对象（比如，XMLHttpRequest、AudioNode、AudioContext）也部署了这个接口。
// 2、EventTarget.addEventListener()：EventTarget.addEventListener()用于在当前节点或对象上，定义一个特定事件的监听函数。一旦这个事件发生，就会执行监听函数。该方法没有返回值。
// 	target.addEventListener(type, listener[, useCapture]);
// 	该方法接受三个参数。
// 		type：事件名称，大小写敏感。
// 		listener：监听函数。事件发生时，会调用该监听函数。
// 		useCapture：布尔值，表示监听函数是否在捕获阶段（capture）触发（参见后文《事件的传播》部分），默认为false（监听函数只在冒泡阶段被触发）。该参数可选。
// 	其次，第三个参数除了布尔值useCapture，还可以是一个属性配置对象。该对象有以下属性。
//         capture：布尔值，表示该事件是否在捕获阶段触发监听函数。
//         once：布尔值，表示监听函数是否只触发一次，然后就自动移除。
//         passive：布尔值，表示监听函数不会调用事件的preventDefault方法。如果监听函数调用了，浏览器将忽略这个要求，并在监控台输出一行警告。
// 3、EventTarget.removeEventListener()：EventTarget.removeEventListener方法用来移除addEventListener方法添加的事件监听函数。该方法没有返回值。
// 4、EventTarget.dispatchEvent()：EventTarget.dispatchEvent方法在当前节点上触发指定事件，从而触发监听函数的执行。该方法返回一个布尔值，只要有一个监听函数调用了Event.preventDefault()，则返回值为false，否则为true。
// 二、事件模型
// 1、监听函数：浏览器的事件模型，就是通过监听函数（listener）对事件做出反应。事件发生后，浏览器监听到了这个事件，就会执行对应的监听函数。这是事件驱动编程模式（event-driven）的主要编程方式。
// 	1.1、HTML 的 on- 属性：HTML 语言允许在元素的属性中，直接定义某些事件的监听代码。
// 	1.2、元素节点的事件属性：元素节点对象的事件属性，同样可以指定监听函数。
// 	1.3、EventTarget.addEventListener()：所有 DOM 节点实例都有addEventListener方法，用来为该节点定义事件的监听函数。
// 	1.4、EventTarget.addEventListener它有如下优点：
// 		同一个事件可以添加多个监听函数。
// 		能够指定在哪个阶段（捕获阶段还是冒泡阶段）触发监听函数。
// 		除了 DOM 节点，其他对象（比如window、XMLHttpRequest等）也有这个接口，它等于是整个 JavaScript 统一的监听函数接口。
// 2、this 的指向：监听函数内部的this指向触发事件的那个元素节点。
// 3、事件的传播：一个事件发生后，会在子元素和父元素之间传播（propagation）。这种传播分成三个阶段。
//     第一阶段：从window对象传导到目标节点（上层传到底层），称为“捕获阶段”（capture phase）。
//     第二阶段：在目标节点上触发，称为“目标阶段”（target phase）。
//     第三阶段：从目标节点传导回window对象（从底层传回上层），称为“冒泡阶段”（bubbling phase）。
// 4、事件的代理：由于事件会在冒泡阶段向上传播到父节点，因此可以把子节点的监听函数定义在父节点上，由父节点的监听函数统一处理多个子元素的事件。这种方法叫做事件的代理。
// 三、Event 对象
// 1、概述：事件发生以后，会产生一个事件对象，作为参数传给监听函数。浏览器原生提供一个Event对象，所有的事件都是这个对象的实例，或者说继承了Event.prototype对象。
// 	Event构造函数接受两个参数。第一个参数type是字符串，表示事件的名称；第二个参数options是一个对象，表示事件对象的配置。该对象主要有下面两个属性。
// 		bubbles：布尔值，可选，默认为false，表示事件对象是否冒泡。
// 		cancelable：布尔值，可选，默认为false，表示事件是否可以被取消，即能否用Event.preventDefault()取消这个事件。一旦事件被取消，就好像从来没有发生过，不会触发浏览器对该事件的默认行为。
// 2、实例属性
// 	2.1、Event.bubbles，Event.eventPhase：
// 		Event.bubbles属性返回一个布尔值，表示当前事件是否会冒泡。该属性为只读属性，一般用来了解 Event 实例是否可以冒泡。前面说过，除非显式声明，Event构造函数生成的事件，默认是不冒泡的。
// 		Event.eventPhase属性返回一个整数常量，表示事件目前所处的阶段。该属性只读。
// 		Event.eventPhase的返回值有四种可能。
// 			0，事件目前没有发生。
// 			1，事件目前处于捕获阶段，即处于从祖先节点向目标节点的传播过程中。
// 			2，事件到达目标节点，即Event.target属性指向的那个节点。
// 			3，事件处于冒泡阶段，即处于从目标节点向祖先节点的反向传播过程中。
// 	2.2、Event.cancelable，Event.cancelBubble，event.defaultPrevented：
// 		Event.cancelable属性返回一个布尔值，表示事件是否可以取消。该属性为只读属性，一般用来了解 Event 实例的特性。
// 		大多数浏览器的原生事件是可以取消的。比如，取消click事件，点击链接将无效。但是除非显式声明，Event构造函数生成的事件，默认是不可以取消的。
// 		当Event.cancelable属性为true时，调用Event.preventDefault()就可以取消这个事件，阻止浏览器对该事件的默认行为。
// 		如果事件不能取消，调用Event.preventDefault()会没有任何效果。所以使用这个方法之前，最好用Event.cancelable属性判断一下是否可以取消。
// 	2.3、Event.currentTarget，Event.target
// 		事件发生以后，会经过捕获和冒泡两个阶段，依次通过多个 DOM 节点。因此，任意时点都有两个与事件相关的节点，一个是事件的原始触发节点（Event.target），另一个是事件当前正在通过的节点（Event.currentTarget）。前者通常是后者的后代节点。
// 		Event.currentTarget属性返回事件当前所在的节点，即事件当前正在通过的节点，也就是当前正在执行的监听函数所在的那个节点。随着事件的传播，这个属性的值会变。
// 		Event.target属性返回原始触发事件的那个节点，即事件最初发生的节点。这个属性不会随着事件的传播而改变。
// 	2.4、Event.type：Event.type属性返回一个字符串，表示事件类型。事件的类型是在生成事件的时候指定的。该属性只读。
// 	2.5、Event.timeStamp：Event.timeStamp属性返回一个毫秒时间戳，表示事件发生的时间。它是相对于网页加载成功开始计算的。
// 	2.6、Event.isTrusted：Event.isTrusted属性返回一个布尔值，表示该事件是否由真实的用户行为产生。比如，用户点击链接会产生一个click事件，该事件是用户产生的；Event构造函数生成的事件，则是脚本产生的。
// 	2.7、Event.detail：Event.detail属性只有浏览器的 UI （用户界面）事件才具有。该属性返回一个数值，表示事件的某种信息。具体含义与事件类型相关。比如，对于click和dblclick事件，
// 		Event.detail是鼠标按下的次数（1表示单击，2表示双击，3表示三击）；对于鼠标滚轮事件，Event.detail是滚轮正向滚动的距离，负值就是负向滚动的距离，返回值总是3的倍数。
// 3、实例方法
// 	3.1、Event.preventDefault()
// 		Event.preventDefault方法取消浏览器对当前事件的默认行为。比如点击链接后，浏览器默认会跳转到另一个页面，使用这个方法以后，就不会跳转了；再比如，按一下空格键，
// 		页面向下滚动一段距离，使用这个方法以后也不会滚动了。该方法生效的前提是，事件对象的cancelable属性为true，如果为false，调用该方法没有任何效果。
// 	3.2、Event.stopPropagation()：stopPropagation方法阻止事件在 DOM 中继续传播，防止再触发定义在别的节点上的监听函数，但是不包括在当前节点上其他的事件监听函数。
// 	3.3、Event.stopImmediatePropagation()：Event.stopImmediatePropagation方法阻止同一个事件的其他监听函数被调用，不管监听函数定义在当前节点还是其他节点。也就是说，该方法阻止事件的传播，比Event.stopPropagation()更彻底。
// 	3.4、Event.composedPath()：Event.composedPath()返回一个数组，成员是事件的最底层节点和依次冒泡经过的所有上层节点。
// 四、鼠标事件
// 1、鼠标事件的种类：鼠标事件指与鼠标相关的事件，继承了MouseEvent接口。具体的事件主要有以下一些。
//     click：按下鼠标（通常是按下主按钮）时触发。
//     dblclick：在同一个元素上双击鼠标时触发。
//     mousedown：按下鼠标键时触发。
//     mouseup：释放按下的鼠标键时触发。
//     mousemove：当鼠标在一个节点内部移动时触发。当鼠标持续移动时，该事件会连续触发。为了避免性能问题，建议对该事件的监听函数做一些限定，比如限定一段时间内只能运行一次。
//     mouseenter：鼠标进入一个节点时触发，进入子节点不会触发这个事件（详见后文）。
//     mouseover：鼠标进入一个节点时触发，进入子节点会再一次触发这个事件（详见后文）。
//     mouseout：鼠标离开一个节点时触发，离开父节点也会触发这个事件（详见后文）。
//     mouseleave：鼠标离开一个节点时触发，离开父节点不会触发这个事件（详见后文）。
//     contextmenu：按下鼠标右键时（上下文菜单出现前）触发，或者按下“上下文菜单键”时触发。
//     wheel：滚动鼠标的滚轮时触发，该事件继承的是WheelEvent接口。
// 2、MouseEvent 接口概述：MouseEvent接口代表了鼠标相关的事件，单击（click）、双击（dblclick）、松开鼠标键（mouseup）、按下鼠标键（mousedown）等动作，所产生的事件对象都是MouseEvent实例。此外，滚轮事件和拖拉事件也是MouseEvent实例。、
//  Event接口的实例配置属性，该对象可以配置以下属性，所有属性都是可选的。
//     screenX：数值，鼠标相对于屏幕的水平位置（单位像素），默认值为0，设置该属性不会移动鼠标。
//     screenY：数值，鼠标相对于屏幕的垂直位置（单位像素），其他与screenX相同。
//     clientX：数值，鼠标相对于程序窗口的水平位置（单位像素），默认值为0，设置该属性不会移动鼠标。
//     clientY：数值，鼠标相对于程序窗口的垂直位置（单位像素），其他与clientX相同。
//     ctrlKey：布尔值，是否同时按下了 Ctrl 键，默认值为false。
//     shiftKey：布尔值，是否同时按下了 Shift 键，默认值为false。
//     altKey：布尔值，是否同时按下 Alt 键，默认值为false。
//     metaKey：布尔值，是否同时按下 Meta 键，默认值为false。
//     button：数值，表示按下了哪一个鼠标按键，默认值为0，表示按下主键（通常是鼠标的左键）或者当前事件没有定义这个属性；1表示按下辅助键（通常是鼠标的中间键），2表示按下次要键（通常是鼠标的右键）。
//     buttons：数值，表示按下了鼠标的哪些键，是一个三个比特位的二进制值，默认为0（没有按下任何键）。1（二进制001）表示按下主键（通常是左键），2（二进制010）表示按下次要键（通常是右键），4（二进制100）表示按下辅助键（通常是中间键）。因此，如果返回3（二进制011）就表示同时按下了左键和右键。
//     relatedTarget：节点对象，表示事件的相关节点，默认为null。mouseenter和mouseover事件时，表示鼠标刚刚离开的那个元素节点；mouseout和mouseleave事件时，表示鼠标正在进入的那个元素节点。
// 3、MouseEvent 接口的实例属性 
// 	3.1、MouseEvent.altKey，MouseEvent.ctrlKey，MouseEvent.metaKey，MouseEvent.shiftKey：
// 	 MouseEvent.altKey、MouseEvent.ctrlKey、MouseEvent.metaKey、MouseEvent.shiftKey这四个属性都返回一个布尔值，表示事件发生时，是否按下对应的键。它们都是只读属性。
// 		altKey属性：Alt 键
// 		ctrlKey属性：Ctrl 键
// 		metaKey属性：Meta 键（Mac 键盘是一个四瓣的小花，Windows 键盘是 Windows 键）
// 		shiftKey属性：Shift 键
// 	3.2、MouseEvent.button，MouseEvent.buttons：
// 	 MouseEvent.button属性返回一个数值，表示事件发生时按下了鼠标的哪个键。该属性只读。
// 		0：按下主键（通常是左键），或者该事件没有初始化这个属性（比如mousemove事件）。
// 		1：按下辅助键（通常是中键或者滚轮键）。
// 		2：按下次键（通常是右键）。
// 	 MouseEvent.buttons属性返回一个三个比特位的值，表示同时按下了哪些键。它用来处理同时按下多个鼠标键的情况。该属性只读。
// 		1：二进制为001（十进制的1），表示按下左键。
// 		2：二进制为010（十进制的2），表示按下右键。
// 		4：二进制为100（十进制的4），表示按下中键或滚轮键。
// 	3.3、MouseEvent.clientX，MouseEvent.clientY：MouseEvent.clientX属性返回鼠标位置相对于浏览器窗口左上角的水平坐标（单位像素），MouseEvent.clientY属性返回垂直坐标。这两个属性都是只读属性。
// 	3.4、MouseEvent.movementX，MouseEvent.movementY：
// 	 MouseEvent.movementX属性返回当前位置与上一个mousemove事件之间的水平距离（单位像素）。数值上，它等于下面的计算公式。
// 	 MouseEvent.movementY属性返回当前位置与上一个mousemove事件之间的垂直距离（单位像素）。数值上，它等于下面的计算公式。
// 	3.5、MouseEvent.screenX，MouseEvent.screenY：
// 	 MouseEvent.screenX属性返回鼠标位置相对于屏幕左上角的水平坐标（单位像素），MouseEvent.screenY属性返回垂直坐标。这两个属性都是只读属性。
// 	3.6、MouseEvent.offsetX，MouseEvent.offsetY：
// 	 MouseEvent.offsetX属性返回鼠标位置与目标节点左侧的padding边缘的水平距离（单位像素），MouseEvent.offsetY属性返回与目标节点上方的padding边缘的垂直距离。这两个属性都是只读属性。
// 	3.7、MouseEvent.pageX，MouseEvent.pageY：
// 	 MouseEvent.pageX属性返回鼠标位置与文档左侧边缘的距离（单位像素），MouseEvent.pageY属性返回与文档上侧边缘的距离（单位像素）。它们的返回值都包括文档不可见的部分。这两个属性都是只读。
// 	3.8、MouseEvent.relatedTarget：
// 	 MouseEvent.relatedTarget属性返回事件的相关节点。对于那些没有相关节点的事件，该属性返回null。该属性只读。
// 4、MouseEvent 接口的实例方法
// 	4.1、MouseEvent.getModifierState()：
// 	 MouseEvent.getModifierState方法返回一个布尔值，表示有没有按下特定的功能键。它的参数是一个表示功能键的字符串。
// 5、WheelEvent 接口 
// 	5.1、概述：WheelEvent 接口继承了 MouseEvent 实例，代表鼠标滚轮事件的实例对象。目前，鼠标滚轮相关的事件只有一个wheel事件，用户滚动鼠标的滚轮，就生成这个事件的实例。
// 	 WheelEvent()构造函数可以接受两个参数，第一个是字符串，表示事件类型，对于滚轮事件来说，这个值目前只能是wheel。第二个参数是事件的配置对象。该对象的属性除了Event、UIEvent的配置属性以外，还可以接受以下几个属性，所有属性都是可选的。
// 		deltaX：数值，表示滚轮的水平滚动量，默认值是 0.0。
// 		deltaY：数值，表示滚轮的垂直滚动量，默认值是 0.0。
// 		deltaZ：数值，表示滚轮的 Z 轴滚动量，默认值是 0.0。
// 		deltaMode：数值，表示相关的滚动事件的单位，适用于上面三个属性。0表示滚动单位为像素，1表示单位为行，2表示单位为页，默认为0。
// 	5.2、实例属性：WheelEvent事件实例除了具有Event和MouseEvent的实例属性和实例方法，还有一些自己的实例属性，但是没有自己的实例方法。
// 	 下面的属性都是只读属性。
// 		WheelEvent.deltaX：数值，表示滚轮的水平滚动量。
// 		WheelEvent.deltaY：数值，表示滚轮的垂直滚动量。
// 		WheelEvent.deltaZ：数值，表示滚轮的 Z 轴滚动量。
// 		WheelEvent.deltaMode：数值，表示上面三个属性的单位，0是像素，1是行，2是页。
// 五、键盘事件
// 1、键盘事件的种类：键盘事件由用户击打键盘触发，主要有keydown、keypress、keyup三个事件，它们都继承了KeyboardEvent接口。
//     keydown：按下键盘时触发。
//     keypress：按下有值的键时触发，即按下 Ctrl、Alt、Shift、Meta 这样无值的键，这个事件不会触发。对于有值的键，按下时先触发keydown事件，再触发这个事件。
//     keyup：松开键盘时触发该事件。
// 	如果用户一直按键不松开，就会连续触发键盘事件，触发的顺序如下。
//     keydown
//     keypress
//     keydown
//     keypress
//     ...（重复以上过程）
//     keyup
// 2、KeyboardEvent 接口概述：KeyboardEvent接口用来描述用户与键盘的互动。这个接口继承了Event接口，并且定义了自己的实例属性和实例方法。
// 	KeyboardEvent构造函数接受两个参数。第一个参数是字符串，表示事件类型；第二个参数是一个事件配置对象，该参数可选。除了Event接口提供的属性，还可以配置以下字段，它们都是可选。
// 		key：字符串，当前按下的键，默认为空字符串。
// 		code：字符串，表示当前按下的键的字符串形式，默认为空字符串。
// 		location：整数，当前按下的键的位置，默认为0。
// 		ctrlKey：布尔值，是否按下 Ctrl 键，默认为false。
// 		shiftKey：布尔值，是否按下 Shift 键，默认为false。
// 		altKey：布尔值，是否按下 Alt 键，默认为false。
// 		metaKey：布尔值，是否按下 Meta 键，默认为false。
// 		repeat：布尔值，是否重复按键，默认为false。
// 3、KeyboardEvent 的实例属性
// 	3.1、KeyboardEvent.altKey，KeyboardEvent.ctrlKey，KeyboardEvent.metaKey，KeyboardEvent.shiftKey
// 	以下属性都是只读属性，返回一个布尔值，表示是否按下对应的键。
// 		KeyboardEvent.altKey：是否按下 Alt 键
// 		KeyboardEvent.ctrlKey：是否按下 Ctrl 键
// 		KeyboardEvent.metaKey：是否按下 meta 键（Mac 系统是一个四瓣的小花，Windows 系统是 windows 键）
// 		KeyboardEvent.shiftKey：是否按下 Shift 键
// 	3.2、KeyboardEvent.code：KeyboardEvent.code属性返回一个字符串，表示当前按下的键的字符串形式。该属性只读。
// 	下面是一些常用键的字符串形式，其他键请查文档。
// 		数字键0 - 9：返回digit0 - digit9
// 		字母键A - z：返回KeyA - KeyZ
// 		功能键F1 - F12：返回 F1 - F12
// 		方向键：返回ArrowDown、ArrowUp、ArrowLeft、ArrowRight
// 		Alt 键：返回AltLeft或AltRight
// 		Shift 键：返回ShiftLeft或ShiftRight
// 		Ctrl 键：返回ControlLeft或ControlRight
// 	3.3、KeyboardEvent.key：KeyboardEvent.key属性返回一个字符串，表示按下的键名。该属性只读。
// 	3.4、KeyboardEvent.location：KeyboardEvent.location属性返回一个整数，表示按下的键处在键盘的哪一个区域。它可能取以下值。
// 		0：处在键盘的主区域，或者无法判断处于哪一个区域。
// 		1：处在键盘的左侧，只适用那些有两个位置的键（比如 Ctrl 和 Shift 键）。
// 		2：处在键盘的右侧，只适用那些有两个位置的键（比如 Ctrl 和 Shift 键）。
// 		3：处在数字小键盘。
// 	3.5、KeyboardEvent.repeat：KeyboardEvent.repeat返回一个布尔值，代表该键是否被按着不放，以便判断是否重复这个键，即浏览器会持续触发keydown和keypress事件，直到用户松开手为止。
// 4、KeyboardEvent 的实例方法
// 	4.1、KeyboardEvent.getModifierState()：
// 	 KeyboardEvent.getModifierState()方法返回一个布尔值，表示是否按下或激活指定的功能键。它的常用参数如下。
// 		Alt：Alt 键
// 		CapsLock：大写锁定键
// 		Control：Ctrl 键
// 		Meta：Meta 键
// 		NumLock：数字键盘开关键
// 		Shift：Shift 键
// 六、进度事件
// 1、进度事件的种类：进度事件用来描述资源加载的进度，主要由 AJAX 请求、<img>、<audio>、<video>、<style>、<link>等外部资源的加载触发，继承了ProgressEvent接口。它主要包含以下几种事件。
//     abort：外部资源中止加载时（比如用户取消）触发。如果发生错误导致中止，不会触发该事件。
//     error：由于错误导致外部资源无法加载时触发。
//     load：外部资源加载成功时触发。
//     loadstart：外部资源开始加载时触发。
//     loadend：外部资源停止加载时触发，发生顺序排在error、abort、load等事件的后面。
//     progress：外部资源加载过程中不断触发。
//     timeout：加载超时时触发。
// 2、ProgressEvent 接口：ProgressEvent接口主要用来描述外部资源加载的进度，比如 AJAX 加载、<img>、<video>、<style>、<link>等外部资源加载。进度相关的事件都继承了这个接口。
// 	ProgressEvent()构造函数接受两个参数。第一个参数是字符串，表示事件的类型，这个参数是必须的。第二个参数是一个配置对象，表示事件的属性，该参数可选。配置对象除了可以使用Event接口的配置属性，还可以使用下面的属性，所有这些属性都是可选的。
// 		lengthComputable：布尔值，表示加载的总量是否可以计算，默认是false。
// 		loaded：整数，表示已经加载的量，默认是0。
// 		total：整数，表示需要加载的总量，默认是0。
// 	ProgressEvent具有对应的实例属性。
// 		ProgressEvent.lengthComputable
// 		ProgressEvent.loaded
// 		ProgressEvent.total
// 七、表单事件
// 1、表单事件的种类
// 	1.1、input 事件：input事件当<input>、<select>、<textarea>的值发生变化时触发。对于复选框（<input type=checkbox>）或单选框（<input type=radio>），用户改变选项时，也会触发这个事件。另外，对于打开contenteditable属性的元素，只要值发生变化，也会触发input事件。
// 	1.2、select 事件：select事件当在<input>、<textarea>里面选中文本时触发。
// 	1.3、change 事件：change事件当<input>、<select>、<textarea>的值发生变化时触发。它与input事件的最大不同，就是不会连续触发，只有当全部修改完成时才会触发，另一方面input事件必然伴随change事件。具体来说，分成以下几种情况。
// 		激活单选框（radio）或复选框（checkbox）时触发。
// 		用户提交时触发。比如，从下列列表（select）完成选择，在日期或文件输入框完成选择。
// 		当文本框或<textarea>元素的值发生改变，并且丧失焦点时触发。
// 	1.4、invalid 事件：用户提交表单时，如果表单元素的值不满足校验条件，就会触发invalid事件。
// 	1.5、reset 事件，submit 事件：这两个事件发生在表单对象<form>上，而不是发生在表单的成员上。
// 		reset事件当表单重置（所有表单成员变回默认值）时触发。
// 		submit事件当表单数据向服务器提交时触发。注意，submit事件的发生对象是<form>元素，而不是<button>元素，因为提交的是表单，而不是按钮。
// 2、InputEvent 接口：InputEvent接口主要用来描述input事件的实例。该接口继承了Event接口，还定义了一些自己的实例属性和实例方法。
// 	浏览器原生提供InputEvent()构造函数，用来生成实例对象。
// 	new InputEvent(type, options)
// 	InputEvent构造函数可以接受两个参数。第一个参数是字符串，表示事件名称，该参数是必需的。第二个参数是一个配置对象，用来设置事件实例的属性，该参数是可选的。配置对象的字段除了Event构造函数的配置属性，还可以设置下面的字段，这些字段都是可选的。
// 		inputType：字符串，表示发生变更的类型（详见下文）。
// 		data：字符串，表示插入的字符串。如果没有插入的字符串（比如删除操作），则返回null或空字符串。
// 		dataTransfer：返回一个 DataTransfer 对象实例，该属性通常只在输入框接受富文本输入时有效。
// 	InputEvent的实例属性主要就是上面三个属性，这三个实例属性都是只读的。
// 	（1）、InputEvent.data：InputEvent.data属性返回一个字符串，表示变动的内容。
// 	（2）、InputEvent.inputType：InputEvent.inputType属性返回一个字符串，表示字符串发生变更的类型。
// 		对于常见情况，Chrome 浏览器的返回值如下。完整列表可以参考文档。
// 			手动插入文本：insertText
// 			粘贴插入文本：insertFromPaste
// 			向后删除：deleteContentBackward
// 			向前删除：deleteContentForward
// 	（3）、InputEvent.dataTransfer：InputEvent.dataTransfer属性返回一个 DataTransfer 实例。该属性只在文本框接受粘贴内容（insertFromPaste）或拖拽内容（insertFromDrop）时才有效。
// 八、触摸事件
// 1、触摸操作概述：浏览器的触摸 API 由三个部分组成。
//     Touch：一个触摸点
//     TouchList：多个触摸点的集合
//     TouchEvent：触摸引发的事件实例
// 2、Touch 接口
// 	2.1、Touch 接口概述：Touch 接口代表单个触摸点。触摸点可能是一根手指，也可能是一根触摸笔。
// 	浏览器原生提供Touch构造函数，用来生成Touch实例。
// 	var touch = new Touch(touchOptions);
// 	Touch构造函数接受一个配置对象作为参数，它有以下属性。
// 		identifier：必需，类型为整数，表示触摸点的唯一 ID。
// 		target：必需，类型为元素节点，表示触摸点开始时所在的网页元素。
// 		clientX：可选，类型为数值，表示触摸点相对于浏览器窗口左上角的水平距离，默认为0。
// 		clientY：可选，类型为数值，表示触摸点相对于浏览器窗口左上角的垂直距离，默认为0。
// 		screenX：可选，类型为数值，表示触摸点相对于屏幕左上角的水平距离，默认为0。
// 		screenY：可选，类型为数值，表示触摸点相对于屏幕左上角的垂直距离，默认为0。
// 		pageX：可选，类型为数值，表示触摸点相对于网页左上角的水平位置（即包括页面的滚动距离），默认为0。
// 		pageY：可选，类型为数值，表示触摸点相对于网页左上角的垂直位置（即包括页面的滚动距离），默认为0。
// 		radiusX：可选，类型为数值，表示触摸点周围受到影响的椭圆范围的 X 轴半径，默认为0。
// 		radiusY：可选：类型为数值，表示触摸点周围受到影响的椭圆范围的 Y 轴半径，默认为0。
// 		rotationAngle：可选，类型为数值，表示触摸区域的椭圆的旋转角度，单位为度数，在0到90度之间，默认值为0。
// 		force：可选，类型为数值，范围在0到1之间，表示触摸压力。0代表没有压力，1代表硬件所能识别的最大压力，默认为0。
// 	2.2、Touch 接口的实例属性 
// 	（1）、Touch.identifier：Touch.identifier属性返回一个整数，表示触摸点的唯一 ID。这个值在整个触摸过程保持不变，直到触摸事件结束。
// 	（2）、Touch.screenX，Touch.screenY，Touch.clientX，Touch.clientY，pageX，pageY：
// 		Touch.screenX属性和Touch.screenY属性，分别表示触摸点相对于屏幕左上角的横坐标和纵坐标，与页面是否滚动无关。
// 		Touch.clientX属性和Touch.clientY属性，分别表示触摸点相对于浏览器视口左上角的横坐标和纵坐标，与页面是否滚动无关。
// 		Touch.pageX属性和Touch.pageY属性，分别表示触摸点相对于当前页面左上角的横坐标和纵坐标，包含了页面滚动带来的位移。
// 	（3）、Touch.radiusX，Touch.radiusY，Touch.rotationAngle：
// 		Touch.radiusX属性和Touch.radiusY属性，分别返回触摸点周围受到影响的椭圆范围的 X 轴半径和 Y 轴半径，单位为像素。乘以 2 就可以得到触摸范围的宽度和高度。
// 	（4）、Touch.force：
// 		Touch.force属性返回一个0到1之间的数值，表示触摸压力。0代表没有压力，1代表硬件所能识别的最大压力。
// 	（5）Touch.target：
// 		Touch.target属性返回一个元素节点，代表触摸发生时所在的那个元素节点。即使触摸点已经离开了这个节点，该属性依然不变。
// 3、TouchList 接口
// 	TouchList接口表示一组触摸点的集合。它的实例是一个类似数组的对象，成员是Touch的实例对象，表示所有触摸点。用户用三根手指触摸，产生的TouchList实例就会包含三个成员，每根手指的触摸点对应一个Touch实例对象。
// 	它的实例主要通过触摸事件的TouchEvent.touches、TouchEvent.changedTouches、TouchEvent.targetTouches这几个属性获取。
// 	它的实例属性和实例方法只有两个。
// 		TouchList.length：数值，表示成员数量（即触摸点的数量）。
// 		TouchList.item()：返回指定位置的成员，它的参数是该成员的位置编号（从零开始）。
// 4、TouchEvent 接口
// 	4.1、概述：TouchEvent 接口继承了 Event 接口，表示由触摸引发的事件实例，通常来自触摸屏或轨迹板。除了被继承的属性以外，它还有一些自己的属性。
// 	浏览器原生提供TouchEvent()构造函数，用来生成触摸事件的实例。
// 	new TouchEvent(type, options)
// 	TouchEvent()构造函数可以接受两个参数，第一个参数是字符串，表示事件类型；第二个参数是事件的配置对象，该参数是可选的，对象的所有属性也是可选的。除了Event接口的配置属性，该接口还有一些自己的配置属性。
// 		touches：TouchList实例，代表所有的当前处于活跃状态的触摸点，默认值是一个空数组[]。
// 		targetTouches：TouchList实例，代表所有处在触摸的目标元素节点内部、且仍然处于活动状态的触摸点，默认值是一个空数组[]。
// 		changedTouches：TouchList实例，代表本次触摸事件的相关触摸点，默认值是一个空数组[]。
// 		ctrlKey：布尔值，表示 Ctrl 键是否同时按下，默认值为false。
// 		shiftKey：布尔值，表示 Shift 键是否同时按下，默认值为false。
// 		altKey：布尔值，表示 Alt 键是否同时按下，默认值为false。
// 		metaKey：布尔值，表示 Meta 键（或 Windows 键）是否同时按下，默认值为false。
// 	4.2、实例属性：TouchEvent 接口的实例具有Event实例的所有属性和方法，此外还有一些它自己的实例属性，这些属性全部都是只读。
// 	（1）TouchEvent.altKey，TouchEvent.ctrlKey，TouchEvent.shiftKey，TouchEvent.metaKey
// 		TouchEvent.altKey：布尔值，表示触摸时是否按下了 Alt 键。
// 		TouchEvent.ctrlKey：布尔值，表示触摸时是否按下了 Ctrl 键。
// 		TouchEvent.shiftKey：布尔值：表示触摸时是否按下了 Shift 键。
// 		TouchEvent.metaKey：布尔值，表示触摸时是否按下了 Meta 键（或 Windows 键）。
// 	（2）TouchEvent.changedTouches
// 	 TouchEvent.changedTouches属性返回一个TouchList实例，成员是一组Touch实例对象，表示本次触摸事件的相关触摸点。
// 	 对于不同的时间，该属性的含义有所不同。
// 		touchstart事件：被激活的触摸点
// 		touchmove事件：发生变化的触摸点
// 		touchend事件：消失的触摸点（即不再被触碰的点）
// 	（3）、TouchEvent.touches：TouchEvent.touches属性返回一个TouchList实例，成员是所有仍然处于活动状态（即触摸中）的触摸点。一般来说，一个手指就是一个触摸点。
// 	（4）TouchEvent.targetTouches：TouchEvent.targetTouches属性返回一个TouchList实例，成员是触摸事件的目标元素节点内部、所有仍然处于活动状态（即触摸中）的触摸点。
// 5、触摸事件的种类：触摸引发的事件，有以下几种。可以通过TouchEvent.type属性，查看到底发生的是哪一种事件。
//     touchstart：用户开始触摸时触发，它的target属性返回发生触摸的元素节点。
//     touchend：用户不再接触触摸屏时（或者移出屏幕边缘时）触发，它的target属性与touchstart事件一致的，就是开始触摸时所在的元素节点。它的changedTouches属性返回一个TouchList实例，包含所有不再触摸的触摸点（即Touch实例对象）。
//     touchmove：用户移动触摸点时触发，它的target属性与touchstart事件一致。如果触摸的半径、角度、力度发生变化，也会触发该事件。
//     touchcancel：触摸点取消时触发，比如在触摸区域跳出一个模态窗口（modal window）、触摸点离开了文档区域（进入浏览器菜单栏）、用户的触摸点太多，超过了支持的上限（自动取消早先的触摸点）。
// 九、拖拉事件
// 1、拖拉事件的种类：拖拉（drag）指的是，用户在某个对象上按下鼠标键不放，拖动它到另一个位置，然后释放鼠标键，将该对象放在那里。
// 	<div draggable="true">
// 	此区域可拖拉
// 	</div>
// 	当元素节点或选中的文本被拖拉时，就会持续触发拖拉事件，包括以下一些事件。
//     drag：拖拉过程中，在被拖拉的节点上持续触发（相隔几百毫秒）。
//     dragstart：用户开始拖拉时，在被拖拉的节点上触发，该事件的target属性是被拖拉的节点。通常应该在这个事件的监听函数中，指定拖拉的数据。
//     dragend：拖拉结束时（释放鼠标键或按下 ESC 键）在被拖拉的节点上触发，该事件的target属性是被拖拉的节点。它与dragstart事件，在同一个节点上触发。不管拖拉是否跨窗口，或者中途被取消，dragend事件总是会触发的。
//     dragenter：拖拉进入当前节点时，在当前节点上触发一次，该事件的target属性是当前节点。通常应该在这个事件的监听函数中，指定是否允许在当前节点放下（drop）拖拉的数据。如果当前节点没有该事件的监听函数，或者监听函数不执行任何操作，
// 		就意味着不允许在当前节点放下数据。在视觉上显示拖拉进入当前节点，也是在这个事件的监听函数中设置。
//     dragover：拖拉到当前节点上方时，在当前节点上持续触发（相隔几百毫秒），该事件的target属性是当前节点。该事件与dragenter事件的区别是，dragenter事件在进入该节点时触发，然后只要没有离开这个节点，dragover事件会持续触发。
//     dragleave：拖拉操作离开当前节点范围时，在当前节点上触发，该事件的target属性是当前节点。如果要在视觉上显示拖拉离开操作当前节点，就在这个事件的监听函数中设置。
//     drop：被拖拉的节点或选中的文本，释放到目标节点时，在目标节点上触发。注意，如果当前节点不允许drop，即使在该节点上方松开鼠标键，也不会触发该事件。如果用户按下 ESC 键，取消这个操作，也不会触发该事件。该事件的监听函数负责取出拖拉数据，并进行相关处理。
// 	关于拖拉事件，有以下几个注意点。
//     拖拉过程只触发以上这些拖拉事件，尽管鼠标在移动，但是鼠标事件不会触发。
//     将文件从操作系统拖拉进浏览器，不会触发dragstart和dragend事件。
//     dragenter和dragover事件的监听函数，用来取出拖拉的数据（即允许放下被拖拉的元素）。由于网页的大部分区域不适合作为放下拖拉元素的目标节点，所以这两个事件的默认设置为当前节点不允许接受被拖拉的元素。如果想要在目标节点上放下的数据，首先必须阻止这两个事件的默认行为。
// 2、DragEvent 接口：拖拉事件都继承了DragEvent接口，这个接口又继承了MouseEvent接口和Event接口。
// 3、DataTransfer 接口概述：所有拖拉事件的实例都有一个DragEvent.dataTransfer属性，用来读写需要传递的数据。这个属性的值是一个DataTransfer接口的实例。
// 4、DataTransfer 的实例属性
// 	4.1、DataTransfer.dropEffect：DataTransfer.dropEffect属性用来设置放下（drop）被拖拉节点时的效果，会影响到拖拉经过相关区域时鼠标的形状。它可能取下面的值。
// 		copy：复制被拖拉的节点
// 		move：移动被拖拉的节点
// 		link：创建指向被拖拉的节点的链接
// 		none：无法放下被拖拉的节点
// 	4.2、DataTransfer.effectAllowed：DataTransfer.effectAllowed属性设置本次拖拉中允许的效果。它可能取下面的值。
// 		copy：复制被拖拉的节点
// 		move：移动被拖拉的节点
// 		link：创建指向被拖拉节点的链接
// 		copyLink：允许copy或link
// 		copyMove：允许copy或move
// 		linkMove：允许link或move
// 		all：允许所有效果
// 		none：无法放下被拖拉的节点
// 		uninitialized：默认值，等同于all
// 	4.3、DataTransfer.files：DataTransfer.files属性是一个 FileList 对象，包含一组本地文件，可以用来在拖拉操作中传送。如果本次拖拉不涉及文件，则该属性为空的 FileList 对象。
// 	4.4、DataTransfer.types：DataTransfer.types属性是一个只读的数组，每个成员是一个字符串，里面是拖拉的数据格式（通常是 MIME 值）。比如，如果拖拉的是文字，对应的成员就是text/plain。
// 	4.5、DataTransfer.items：DataTransfer.items属性返回一个类似数组的只读对象（DataTransferItemList 实例），每个成员就是本次拖拉的一个对象（DataTransferItem 实例）。如果本次拖拉不包含对象，则返回一个空对象。
// 		DataTransferItemList 实例具有以下的属性和方法。
// 			length：返回成员的数量
// 			add(data, type)：增加一个指定内容和类型（比如text/html和text/plain）的字符串作为成员
// 			add(file)：add方法的另一种用法，增加一个文件作为成员
// 			remove(index)：移除指定位置的成员
// 			clear()：移除所有的成员
// 		DataTransferItem 实例具有以下的属性和方法。
// 			kind：返回成员的种类（string还是file）。
// 			type：返回成员的类型（通常是 MIME 值）。
// 			getAsFile()：如果被拖拉是文件，返回该文件，否则返回null。
// 			getAsString(callback)：如果被拖拉的是字符串，将该字符传入指定的回调函数处理。该方法是异步的，所以需要传入回调函数。
// 5、DataTransfer 的实例方法
// 	5.1、DataTransfer.setData()：DataTransfer.setData()方法用来设置拖拉事件所带有的数据。该方法没有返回值。
// 	5.2、DataTransfer.getData()：DataTransfer.getData()方法接受一个字符串（表示数据类型）作为参数，返回事件所带的指定类型的数据（通常是用setData方法添加的数据）。如果指定类型的数据不存在，则返回空字符串。通常只有drop事件触发后，才能取出数据。
// 	5.3、DataTransfer.clearData()：DataTransfer.clearData()方法接受一个字符串（表示数据类型）作为参数，删除事件所带的指定类型的数据。如果没有指定类型，则删除所有数据。如果指定类型不存在，则调用该方法不会产生任何效果。
// 	5.4、DataTransfer.setDragImage()：拖动过程中（dragstart事件触发后），浏览器会显示一张图片跟随鼠标一起移动，表示被拖动的节点。这张图片是自动创造的，通常显示为被拖动节点的外观，不需要自己动手设置。
// 十、其他常见事件
// 1、资源事件
// 	1.1、beforeunload 事件：beforeunload事件在窗口、文档、各种资源将要卸载前触发。它可以用来防止用户不小心卸载资源。
// 	1.2、unload 事件：unload事件在窗口关闭或者document对象将要卸载时触发。它的触发顺序排在beforeunload、pagehide事件后面。
// 	1.3、load 事件，error 事件：
// 		load事件在页面或某个资源加载成功时触发。注意，页面或资源从浏览器缓存加载，并不会触发load事件。
// 		error事件是在页面或资源加载失败时触发。abort事件在用户取消加载时触发。
// 2、session 历史事件
// 	2.1、pageshow 事件，pagehide 事件：默认情况下，浏览器会在当前会话（session）缓存页面，当用户点击“前进/后退”按钮时，浏览器就会从缓存中加载页面。
// 		pageshow事件在页面加载时触发，包括第一次加载和从缓存加载两种情况。如果要指定页面每次加载（不管是不是从浏览器缓存）时都运行的代码，可以放在这个事件的监听函数。
// 		pagehide事件与pageshow事件类似，当用户通过“前进/后退”按钮，离开当前页面时触发。它与 unload 事件的区别在于，如果在 window 对象上定义unload事件的监听函数之后，页面不会保存在缓存中，而使用pagehide事件，页面会保存在缓存中。
// 	2.2、popstate 事件：
// 		popstate事件在浏览器的history对象的当前记录发生显式切换时触发。注意，调用history.pushState()或history.replaceState()，并不会触发popstate事件。该事件只在用户在history记录之间显式切换时触发，
// 		比如鼠标点击“后退/前进”按钮，或者在脚本中调用history.back()、history.forward()、history.go()时触发。
// 	2.3、hashchange 事件：hashchange事件在 URL 的 hash 部分（即#号后面的部分，包括#号）发生变化时触发。该事件一般在window对象上监听。
// 3、网页状态事件
// 	3.1、DOMContentLoaded 事件：
// 		网页下载并解析完成以后，浏览器就会在document对象上触发 DOMContentLoaded 事件。这时，仅仅完成了网页的解析（整张页面的 DOM 生成了），所有外部资源（样式表、脚本、iframe 等等）可能还没有下载结束。也就是说，这个事件比load事件，发生时间早得多。
// 	3.2、readystatechange 事件：
// 		readystatechange事件当 Document 对象和 XMLHttpRequest 对象的readyState属性发生变化时触发。document.readyState有三个可能的值：loading（网页正在加载）、
// 		interactive（网页已经解析完成，但是外部资源仍然处在加载状态）和complete（网页和所有外部资源已经结束加载，load事件即将触发）。
// 4、窗口事件
// 	4.1、scroll 事件：scroll事件在文档或文档元素滚动时触发，主要出现在用户拖动滚动条。
// 	4.2、resize 事件：resize事件在改变浏览器窗口大小时触发，主要发生在window对象上面。
// 	4.3、fullscreenchange 事件，fullscreenerror 事件：
// 		fullscreenchange事件在进入或退出全屏状态时触发，该事件发生在document对象上面
// 		fullscreenerror事件在浏览器无法切换到全屏状态时触发。
// 5、剪贴板事件
// 	以下三个事件属于剪贴板操作的相关事件。
// 		cut：将选中的内容从文档中移除，加入剪贴板时触发。
// 		copy：进行复制动作时触发。
// 		paste：剪贴板内容粘贴到文档后触发。
// 6、焦点事件：
// 	焦点事件发生在元素节点和document对象上面，与获得或失去焦点相关。它主要包括以下四个事件。
// 		focus：元素节点获得焦点后触发，该事件不会冒泡。
// 		blur：元素节点失去焦点后触发，该事件不会冒泡。
// 		focusin：元素节点将要获得焦点时触发，发生在focus事件之前。该事件会冒泡。
// 		focusout：元素节点将要失去焦点时触发，发生在blur事件之前。该事件会冒泡。
// 	这四个事件的事件对象都继承了FocusEvent接口。FocusEvent实例具有以下属性。
// 		FocusEvent.target：事件的目标节点。
// 		FocusEvent.relatedTarget：对于focusin事件，返回失去焦点的节点；对于focusout事件，返回将要接受焦点的节点；对于focus和blur事件，返回null。
// 7、CustomEvent 接口
// 	CustomEvent 接口用于生成自定义的事件实例。那些浏览器预定义的事件，虽然可以手动生成，但是往往不能在事件上绑定数据。如果需要在触发事件的同时，传入指定的数据，就可以使用 CustomEvent 接口生成的自定义事件对象。
// 十一、GlobalEventHandlers 接口
// 1、GlobalEventHandlers.onabort：某个对象的abort事件（停止加载）发生时，就会调用onabort属性指定的回调函数。
// 2、GlobalEventHandlers.onerror
// 	error事件发生时，就会调用onerror属性指定的回调函数。
// 	error事件分成两种。
// 	一种是 JavaScript 的运行时错误，这会传到window对象，导致window.onerror()。
// 	window.onerror = function (message, source, lineno, colno, error) {
// 	// ...
// 	}
// 	window.onerror的处理函数共接受五个参数，含义如下。
// 		message：错误信息字符串
// 		source：报错脚本的 URL
// 		lineno：报错的行号，是一个整数
// 		colno：报错的列号，是一个整数
// 		error： 错误对象
// 3、GlobalEventHandlers.onload、GlobalEventHandlers.onloadstart
// 	元素完成加载时，会触发load事件，执行onload()。它的典型使用场景是window对象和<img>元素。对于window对象来说，只有页面的所有资源加载完成（包括图片、脚本、样式表、字体等所有外部资源），才会触发load事件。
// 4、GlobalEventHandlers.onfocus，GlobalEventHandlers.onblur
// 	当前元素获得焦点时，会触发element.onfocus；失去焦点时，会触发element.onblur。
// 5、GlobalEventHandlers.onscroll：页面或元素滚动时，会触发scroll事件，导致执行onscroll()。
// 6、GlobalEventHandlers.oncontextmenu，GlobalEventHandlers.onshow
// 	用户在页面上按下鼠标的右键，会触发contextmenu事件，导致执行oncontextmenu()。如果该属性执行后返回false，就等于禁止了右键菜单。document.oncontextmenu与window.oncontextmenu效果一样。
// 7、其他的事件属性：
// 	鼠标的事件属性。
// 		onclick
// 		ondblclick
// 		onmousedown
// 		onmouseenter
// 		onmouseleave
// 		onmousemove
// 		onmouseout
// 		onmouseover
// 		onmouseup
// 		onwheel
// 	键盘的事件属性。
// 		onkeydown
// 		onkeypress
// 		onkeyup
// 	焦点的事件属性。
// 		onblur
// 		onfocus
// 	表单的事件属性。
// 		oninput
// 		onchange
// 		onsubmit
// 		onreset
// 		oninvalid
// 		onselect
// 	触摸的事件属性。
// 		ontouchcancel
// 		ontouchend
// 		ontouchmove
// 		ontouchstart
// 	拖动的事件属性分成两类：一类与被拖动元素相关，另一类与接收被拖动元素的容器元素相关。
// 	被拖动元素的事件属性。
// 		ondragstart：拖动开始
// 		ondrag：拖动过程中，每隔几百毫秒触发一次
// 		ondragend：拖动结束
// 	接收被拖动元素的容器元素的事件属性。
// 		ondragenter：被拖动元素进入容器元素。
// 		ondragleave：被拖动元素离开容器元素。
// 		ondragover：被拖动元素在容器元素上方，每隔几百毫秒触发一次。
// 		ondrop：松开鼠标后，被拖动元素放入容器元素。
// 	<dialog>对话框元素的事件属性。
// 		oncancel
// 		onclose